<template>
  <div class="workspace-box">
    <Layout :style="mainBoxStyle">
      <LayoutSider style="width: 256px" width="256px">
        <div :style="leftDatabaseListStyle" class="dingScrollStyle">
          <Menu
            v-model:selectedKeys="leftDatabaseList.selectedKeys"
            style="width: 100%"
            mode="inline"
            :open-keys="leftDatabaseList.openKeys"
            :items="databaseItemsList"
            @click="onClickLeftDatabaseList"
          ></Menu>
        </div>
      </LayoutSider>
      <LayoutContent>
        <Tabs
          v-model:activeKey="activeTabKey"
          size="middle"
          type="editable-card"
          @edit="onEdit"
          :tabBarGutter="5"
        >
          <template #addIcon>
            <PlusOutlined />
            <span class="tabs-new-tab">&nbsp;新建查询</span>
          </template>
          <!-- 固定tab页，表信息 -->
          <Tabs.TabPane key="tableInfo" :closable="false">
            <template #tab>
              <span>
                <TableOutlined />
                表信息
              </span>
            </template>
            <template #default>
              <Layout>
                <LayoutSider style="width: 200px" width="200px">
                  <div :style="tableListStyle" class="dingScrollStyle">
                    <Button @click="onCreateTableClick" type="dashed" style="width: 100%">
                      <PlusOutlined />
                      新建表
                    </Button>

                    <List
                      item-layout="horizontal"
                      style="cursor: pointer"
                      :data-source="tableList.items"
                      size="small"
                    >
                      <template #renderItem="{ item }">
                        <List.Item @click="onClickSelectOneTable(item)">
                          <List.Item.Meta>
                            <template #title>
                              <span :style="tableItemStyle(item)"> {{ item.name }} </span>
                            </template>
                            <template #avatar>
                              <!-- <a-avatar src="https://joeschmoe.io/api/v1/random" /> -->
                              <TableOutlined :style="tableItemIconStyle(item)" />
                            </template>
                            <template #description>
                              <span style="font-size: 11px" :style="tableItemStyle(item)">{{
                                item.comment
                              }}</span>
                            </template>
                          </List.Item.Meta>
                        </List.Item>
                      </template>
                    </List>
                  </div>
                </LayoutSider>
                <LayoutContent>
                  <!-- 右侧表格，展示一个表格的字段列表 -->
                  <div>
                    <FieldList ref="fieldListRef" :operator="fieldOperator"></FieldList>
                  </div>
                </LayoutContent>
              </Layout>
            </template>
          </Tabs.TabPane>

          <Tabs.TabPane
            v-for="pane in panes"
            :key="pane.key"
            :tab="pane.title"
            :closable="pane.closable"
          >
            <CreateTable v-if="pane.type === 'tableCreator'" :data="pane.data"></CreateTable>
            <div v-else-if="pane.type === 'newQuery'">
              <div>
                <span>
                  当前数据源： <Tag color="green">{{ pane.data.dsName }} </Tag></span
                >&nbsp;&nbsp;&nbsp;&nbsp;
                <span>
                  当前数据库： <Tag color="green"> {{ pane.data.databaseName }}</Tag></span
                >
              </div>
              <div style="width: 100%; height: 8px"></div>
              <MonacoEditor
                width="100%"
                :height="300"
                @onQuery="onQuery($event, pane)"
              ></MonacoEditor>
              <div>
                <Textarea v-model:value="queryResult" placeholder="查询结果" :rows="4" />
              </div>
            </div>
          </Tabs.TabPane>
        </Tabs>
      </LayoutContent>
    </Layout>
  </div>
</template>

<script setup lang="tsx">
  import { VueElement, reactive, CSSProperties, ref, computed, SetupContext } from 'vue';

  import {
    MailOutlined,
    AppstoreOutlined,
    SettingOutlined,
    TableOutlined,
    PlusOutlined,
    DatabaseOutlined,
    PlusCircleOutlined,
  } from '@ant-design/icons-vue';
  import {
    Button,
    Input,
    ItemType,
    Layout,
    LayoutContent,
    LayoutSider,
    Table,
    Tabs,
    message,
  } from 'ant-design-vue';
  import { Menu, Textarea, Tag, List, TypographyLink, Popconfirm, Switch } from 'ant-design-vue';
  import {
    getDatabasesList,
    execRawSql,
    getTableList,
    getFieldsList,
    IFieldObject,
    updateOneField,
    addOneField,
    deleteOneField,
  } from '@/api/goMyAdmin';
  import { useRoute } from 'vue-router';
  import MonacoEditor from './component/MonacoEditor.vue';
  import setting from '@/settings/projectSetting';
  import { useI18n } from '@/hooks/web/useI18n';
  import { sleep } from '@/utils';
  import CreateTable from './component/CreateTable.vue';
  import FieldList from './component/FieldList.vue';

  const { t } = useI18n();
  const route = useRoute();

  const mainBoxStyle: CSSProperties = {
    'box-sizing': 'border-box',
    margin: '10px',
    borderRadius: '10px',
    overflow: 'hidden',
    background: '#ffffff',
  };

  const leftDatabaseListStyle: CSSProperties = {
    height: window.innerHeight - 100 + 'px',
    overflowX: 'hidden',
    overflowY: 'scroll',
    backgroundColor: '#ffffff',
  };

  const tableListStyle: CSSProperties = {
    height: window.innerHeight - 166 + 'px',
    width: '100%',
    overflowX: 'hidden',
    overflowY: 'scroll',
    backgroundColor: '#ffffff',
  };

  function getItem(
    label: VueElement | string,
    key: string,
    icon?: any,
    children?: ItemType[],
    type?: 'group',
  ): ItemType {
    return {
      key,
      icon,
      children,
      label,
      type,
    } as ItemType;
  }

  const databaseItemsList = ref<ItemType[]>([
    // getItem('Navigation One', 'sub1', () => h(MailOutlined), [
    //   getItem('Option 1', '1'),
    //   getItem('Option 2', '2'),
    //   getItem('Option 3', '3'),
    //   getItem('Option 4', '4'),
    // ]),
    // getItem('Navigation Two', 'sub2', () => h(AppstoreOutlined), [
    //   getItem('Option 5', '5'),
    //   getItem('Option 6', '6'),
    //   getItem('Submenu', 'sub3', null, [getItem('Option 7', '7'), getItem('Option 8', '8')]),
    // ]),
    // getItem('Navigation Three', 'sub4', () => h(SettingOutlined), [
    //   getItem('Option 9', '9'),
    //   getItem('Option 10', '10'),
    //   getItem('Option 11', '11'),
    //   getItem('Option 12', '12'),
    // ]),
  ]);

  const leftDatabaseList = reactive({
    rootSubmenuKeys: [] as string[],
    openKeys: [] as string[],
    selectedKeys: [] as string[],
  });

  const selectedDatabaseName = ref('');

  /** 左侧数据库列表选择click事件 */
  const onClickLeftDatabaseList: any = async (param: {
    key: string;
    keyPath: string[];
    item: ItemType;
  }) => {
    tableList.items = [];
    fieldListRef.value?.clearData();
    const r = await getTableList({ dsId: getDsId(), databaseName: param.key });
    await sleep(100);
    selectedDatabaseName.value = param.key;
    // console.log(r);
    tableList.items = r.tables;
    fieldListRef.value?.clearData();
  };

  async function initGetDatabasesList() {
    const dsId = getDsId();

    const list = await getDatabasesList({ dsId });
    if (list.length > 0) {
      databaseItemsList.value = list.map((item) => {
        return getItem(item.name, item.name, () => <DatabaseOutlined />);
      });
    }
    // console.log(list);
  }

  /** tabs当前激活的标签 */
  const activeTabKey = ref('tableInfo');

  const getRandomKey = () => {
    return `newTab${new Date().getTime()}`;
  };

  type paneObject = {
    type: 'tableCreator' | 'newQuery';
    title: string;
    key: string;
    closable: boolean;
    data: { dsId: number; dsName: string; databaseName: string };
  };
  const panes = ref<paneObject[]>([]);

  /** tab标签添加或删除事件 */
  const onEdit = async (key, action: 'add' | 'remove') => {
    if (action === 'add') {
      const dbName = leftDatabaseList.selectedKeys[0] || 'mysql';
      const panel: paneObject = {
        type: 'newQuery',
        title: dbName + ' - 新建查询',
        // content: 'Content of new Tab',
        key: getRandomKey(),
        closable: true,
        data: {
          dsId: getDsId(),
          dsName: getDsName(),
          databaseName: dbName,
        },
      };
      panes.value.push(panel);
      activeTabKey.value = panel.key;
    } else {
      panes.value = panes.value.filter((pane) => pane.key !== key);
    }
    console.log(key, action);
  };

  const getDsId = () => {
    const dsId = route.query.dsId;
    if (!dsId) throw new Error('dsId不能为空');
    const a = Number(dsId);
    if (Number.isNaN(a)) throw new Error('dsId不是数字');
    return a;
  };

  const getDsName = () => {
    const dsName = route.query.dsName as string;
    return dsName || 'unknown';
  };

  /** 查询结果，用于显示 */
  const queryResult = ref('');
  const onQuery = async (data: { sql: string }, pane: paneObject) => {
    try {
      const res = await execRawSql({
        dsId: pane.data.dsId || getDsId(),
        databaseName: pane.data.databaseName,
        sql: data.sql,
      });
      queryResult.value = JSON.stringify(res);
    } catch (error: any) {
      queryResult.value = error.message;
    }
  };

  type TableItemObject = { name: string; comment?: string; isSelected?: boolean };

  const tableList = reactive({
    selectedKeys: [] as string[],
    openKeys: [] as string[],
    items: [] as TableItemObject[],
  });

  const selectedTableObject = ref<TableItemObject>({} as any);

  /** 表item点击事件 */
  const onClickSelectOneTable = async (item: TableItemObject) => {
    fieldListRef.value?.clearData();
    item.isSelected = true;
    selectedTableObject.value = item;
    tableList.items.forEach((i) => {
      if (i.name !== item.name) {
        i.isSelected = false;
      }
    });
    console.log(item);
    // 加载该表格的字段列表
    loadTablesFieldList(item.name);
  };

  const tableItemStyle = (item: TableItemObject) => {
    if (item.isSelected) {
      return {
        color: setting.themeColor,
      };
    }
    return {};
  };

  const tableItemIconStyle = (item: TableItemObject) => {
    if (item.isSelected) {
      return {
        color: setting.themeColor,
      };
    }
    return {};
  };

  const fieldListRef = ref<InstanceType<typeof FieldList> | null>(null);

  const loadTablesFieldList = async (tableName: string) => {
    const dsId = getDsId();
    const fields = await getFieldsList({
      dsId: dsId,
      databaseName: selectedDatabaseName.value,
      tableName,
    });

    const fieldsList = fields.map((i) => {
      return {
        ...i,
        origin: JSON.parse(JSON.stringify(i)) as IFieldObject,
      };
    });

    fieldListRef.value?.setListData(fieldsList);
  };

  const saveOneRow = async (
    index: number,
    row: goMyAdmin.workspace.TFieldObject | goMyAdmin.workspace.TNewAddFieldObject,
  ) => {
    if (!row.name) {
      message.error(`字段名称不能为空`);
      return;
    }
    const addRow = async (row: goMyAdmin.workspace.TNewAddFieldObject) => {
      await addOneField({
        dsId: getDsId(),
        databaseName: selectedDatabaseName.value,
        tableName: selectedTableObject.value.name || '',
        field: { ...row },
        // 另挂载字段，添加时放在字段后面，mysql支持
        afterField: (row as any).afterField || '',
      });
      delete row.isNewAdd;
      row.origin.name = row.name;

      (row as any).afterField = '';
      message.success('新增成功');
    };
    const updateRow = async (row: goMyAdmin.workspace.TFieldObject) => {
      row.isNull = !row.isNotNull;
      const originRow = row.origin;
      const oldFieldName = originRow.name;
      // console.log(index, row);
      await updateOneField({
        dsId: getDsId(),
        databaseName: selectedDatabaseName.value,
        tableName: selectedTableObject.value.name || '',
        oldFieldName,
        field: { ...row },
      });
      row.origin.name = row.name; // 保存成功后，origin上面的name更新为新的值
      message.success('修改成功');
    };

    if ('isNewAdd' in row) {
      await addRow(row);
    } else {
      await updateRow(row);
    }
  };

  const fieldOperator = (params: { text: string; index: number; record: any }) => {
    return (
      <div class="editable-row-operations">
        <Popconfirm title="警告" onConfirm={() => saveOneRow(params.index, params.record as any)}>
          {{
            description: () => (
              <div style="width: 200px">
                <div>确定修改字段？</div>
                <div>请谨慎操作，字段类型或名称改变可能导致数据丢失！！</div>
              </div>
            ),
            default: () => (
              <Button type="link" size="small">
                {t('common.saveText')}
              </Button>
            ),
          }}
        </Popconfirm>
        <Popconfirm
          title="危险操作"
          onConfirm={() => oneRowDeleteFieldClick(params.record, params.index)}
        >
          {{
            description: () => (
              <div style="width: 200px">
                <div>确定删除字段？</div>
                <div>请谨慎操作，可能导致数据丢失！！</div>
              </div>
            ),
            default: () => (
              <Button danger type="link" size="small">
                {t('common.delText')}
              </Button>
            ),
          }}
        </Popconfirm>
      </div>
    );
  };

  /** 行，删除字段按钮 */
  const oneRowDeleteFieldClick = async (
    record: goMyAdmin.workspace.TFieldObject,
    index: number,
  ) => {
    // console.log(record, index);
    await deleteOneField({
      dsId: getDsId(),
      databaseName: selectedDatabaseName.value,
      tableName: selectedTableObject.value.name || '',
      fieldName: record.name,
    });
    message.success('删除成功');

    fieldListRef.value?.removeOne(index);

    // fieldList.value = [];
    // await loadTablesFieldList(selectedTableObject.value.name || '');
  };

  /** 创建表按钮，添加一个Tab，专用于创建表 */
  const onCreateTableClick = () => {
    const dsId = getDsId();
    const databaseName = selectedDatabaseName.value;
    if (!dsId || !databaseName) {
      message.error('请选择数据库再操作');
      return;
    }
    const panel: paneObject = {
      type: 'tableCreator',
      title: databaseName + ' - 新建表',
      // content: 'Content of new Tab',
      key: getRandomKey(),
      closable: true,
      data: {
        dsId: getDsId(),
        dsName: getDsName(),
        databaseName: databaseName,
      },
    };
    panes.value.push(panel);
    activeTabKey.value = panel.key;
  };

  // init exec
  initGetDatabasesList();
</script>

<style scoped lang="less">
  .workspace-box {
    :deep(.field-plus-box) {
      // padding-left: 16px;
      display: flex;
      position: relative;

      .plus-box {
        width: 22px;
        margin-right: 4px;
        opacity: 0;
        color: #1890ff;
        font-size: 22px;
        text-align: left;
        cursor: pointer;
      }
    }

    /* 实现row hover 显示添加图标 */
    :deep(.field-row-hover) {
      &:hover {
        .plus-box {
          opacity: 1;
        }
      }
    }
  }
</style>
